#!/usr/bin/env python

import os
import sys
import string
import traceback
import signal
import pytoss
from pytoss.users import UserManager
from pytoss.tasks import TaskManager
from pytoss.tasks import TaskExecutionError
from pytoss.receipts import ReceiptManager
from pytoss.receipts import TextualReceipt
from pytoss.flags import FlagManager
from pytoss.flags import Flag
from pytoss.interaction import IOController

raw_print = IOController.get_instance().raw_print

def indent_description(desc):
    return pytoss.utils.indent_multiline_string(desc, TaskManager.get_instance().len_of_longest_task_name() + 7).strip()

# signal handling
def toss_signal_handler(signum, frame):
    raw_print("")
    pytoss.interaction.StreamMonitorTracker.get_instance().ask_all_monitors_to_force_quit()

signals_to_handle = [
    signal.SIGHUP,
    signal.SIGINT,
    signal.SIGQUIT,
    signal.SIGTRAP,
    signal.SIGABRT,
]

for sig in signals_to_handle:
    signal.signal(sig, toss_signal_handler)

try:
    terminal_cols = int(os.environ['COLUMNS'])
    terminal_cols = min([terminal_cols, 80])
except:
    terminal_rows = 0
    terminal_cols = 0


Flag("dry-run").explain("shows the sequence of commands without actually executing them")
if Flag("dry-run").given:
    UserManager.get_instance().force_all_users_to_use_dry_run_strategies()


# collect all tasks by importing the local tossfile
pytoss.Tossfile( os.path.abspath( os.getcwd() ) )


# otherwise, consider the first argument to be a Task name
non_flag_args = []
for arg in sys.argv[1:]:
    if not arg.startswith("--"):
        non_flag_args.append(arg)

if len(non_flag_args) >= 1:
    
    # we have a task to execute
    raw_print(">"*terminal_cols)
    task_name = non_flag_args[0]
    task = TaskManager.get_instance().find_task(task_name)
    
    # by default, if no receipts were specified then we create
    # a TextualReceipt on stdout
    if len( ReceiptManager.get_instance().receipts ) == 0:
        default_receipt = TextualReceipt(sys.stderr)
        ReceiptManager.get_instance().add_receipt( default_receipt )
    
    if task:
        try:
            try:
                task.execute()
                raw_print("<"*terminal_cols)
                raw_print("success!")
            except TaskExecutionError:
                raw_print("<"*terminal_cols)
                raw_print("failed, check the receipt for details")
        except:
            raw_print("*** fatal pytoss error")
            backtrace = traceback.format_tb(sys.exc_info()[2])
            raw_print("\n%s: %s" % (sys.exc_info()[0], sys.exc_info()[1]))
            raw_print("".join(backtrace))
            sys.exit(1)

        sys.exit(0)
        
    else:
        raw_print("<"*terminal_cols)
        raw_print("no task exists by the name '%s'" % task_name)
        sys.exit(1)
        
else:
    
    # no task given, show the list of tasks
    raw_print("="*terminal_cols)
    
    tasks = TaskManager.get_instance().get_all_tasks()
    
    root_tasks = []
    namespaced_tasks = []
    for task in tasks:
        if task.name.find(".") == -1 and task.name.find(pytoss.utils.os_path_separator) == -1:
            root_tasks.append(task)
        else:
            namespaced_tasks.append(task)
    
    max_len = TaskManager.get_instance().len_of_longest_task_name()
    format_string = "  toss %%-%ss  # %%s" % max_len
    current_namespace = None
    
    for task in root_tasks:
        if task.description:
            desc = task.description
        else:
            desc = ""
        raw_print(format_string % (task.name, indent_description(desc)))
    
    for task in namespaced_tasks:    
        last_slash_index = task.name.rfind(pytoss.utils.os_path_separator)
        if last_slash_index != -1:
            pre_namespace = task.name[0:last_slash_index]
        else:
            pre_namespace = ""
        if "." in task.name:
            new_namespace = pre_namespace + task.name.split(".")[0]
        else:
            new_namespace = pre_namespace

        if new_namespace != current_namespace:
            # new namespace
            raw_print("")
            current_namespace = new_namespace
        if task.description:
            desc = task.description
        else:
            desc = ""
        raw_print(format_string % (task.name, indent_description(desc)))
        
    raw_print("")
    explanations = FlagManager.get_instance().get_all_explanations()
    for tossflag_name in explanations:
        raw_print("  [--%s] %s" % (tossflag_name, explanations[tossflag_name]))
    
    raw_print("="*terminal_cols)
    sys.exit(0)
    